// 接口：抽象类(有抽象的和非抽象的) 和接口(都是抽象的) 接口没有具体的实现
// 用来描述形状的 结构   定义结构到时候让用户去实现

// 描述形状  对象 类 函数  混合类型
// 定义一些含没有实现的内容



type IFullname = {
    firstname:string,
    lastname:string
}
interface IFullname1{
    firstname:string,
    lastname:string
}
const getFullName = ({firstname,lastname}:IFullname)=>{
    return firstname + lastname
}

getFullName({firstname:'j',lastname:'w'})

// type和interface的区别
// interface通常描述对象  类的结构比较多  type来描述函数的签名，联合类型 工具类型  映射条件类型
// 使用原则：尽量用type，不能用type的时候  考虑interface

// type 优点：可以用联合类型，不能重名，type中可以用后续的条件类型 映射
// interface 能重名(重名是合并)，可被扩展和实现  继承 混合类型


// 方法计数器  调用则+1
// 用这个其实函数也是对象所以可以用这种方式
interface ICount{
    ():number
    count:number
}
// 因为let声明的变量可以修改，改了后可能属性就不存在了，意味着可能访问不到，不安全
// let counter...
const counter:ICount=()=>{
    return counter.count++
}
counter.count = 0

// 对象采用接口来实现 描述后端返回的数据接口

// 可有可无 怎么处理？
// 1.直接as断言 但是不能取多余的属性 因为不知道有没有
// 2.采用可选属性来标示:?
// 3.我再基于当前类型声明一个新的类型
// 4.同名接口可以合并
// 5.[xxx:string]:any 任意类型
interface IVeg {
    color:string,
    taste:string,
    size:number
    // 对象的key有三种 sting  number  symbol
    [key:string]:any
}
// 可以加readonly
interface IVegWithX extends IVeg{
   readonly xx?:number
}
let veg:IVeg={
    color:'red',
    taste:'sour',
    size:10,
    xx:1 //可有可无  直接断言 
} as IVeg

let veg2:IVegWithX={
    color:'red',
    taste:'sour',
    size:10,
    xx:1
}

// 任意类型-》索引类型

interface IArr{
    [key:number]:any //可能是数字索引 数组
}
const arr:IArr = [1,2,3,'afc']
const obj:IArr={
    0:100,
    '1':30,
    3:200
}
// 可以通过索引访问符号 来访问接口中的属性类型
interface Person{
    name:string,
    age:string,
    address:{
        num:string
    }
    // [key:string]:any 如果写了任意类型 就是任意类型
}
// 这里面不能用点.来取值
type PersonName = Person["name"]
type PersonName1 = Person["address"]["num"]
type PropTypeUnion = keyof Person //拿到的是name age address。。取的key
type PropsTypeValueUnion = Person[keyof Person]  //这个是取值

// 接口最常用的就是描述对象 可以通过索引操作[] 来访问内部类型

// 类接口 描述类中的属性和方法
interface Speakable{
    name:string
    // speak:() =>void  注意这个是实例上的
    speak():void //原型方法 还是实例方法------原型方法
}
interface SpeakChinese{
    speakChines():void
}
interface SpeakEnglish extends Speakable{

}
class Speak implements Speakable ,SpeakChinese{//抽象类
    name!:string
    speak(): void {
        throw new Error('AA')
    }
    speakChines():void{
        throw new Error('BB')
    }
}

// 描述实例类型
// 类 类型 描述的是实例  想获取到类本身的类型 需要采用typeof 获取
class Animal {}
class Meat{}
// function createInstance(clazz: Animal){ 这个代表的是类本身的类型
// function createInstance(clazz:typeof Animal):Animal{//如果要去类的内的属性 用typeof
interface Clazz<T>{
    new ():T
}
/* type IClass={
    new ()  :any
} */
// typeof Clazz -> new ():Clazz
// 泛型类似于函数的参数
function createInstance<T>(clazz:Clazz<T>){//如果要去类的内的属性 用typeof
    return new clazz()
}
// let instance = createInstance<Animal>(Animal)
let instance = createInstance(Animal)




export {}